package com.cloudspace.yunloan.utils;

import android.app.Activity;
import android.content.Context;
import android.os.Environment;
import android.os.StatFs;
import android.os.storage.StorageManager;
import android.text.TextUtils;
import android.util.Log;

import com.cloudspace.yunloan.R;
import com.cloudspace.yunloan.ext.aq.AQUtility;
import com.cloudspace.yunloan.log.APPLog;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Random;
import java.util.concurrent.ConcurrentLinkedQueue;

public class SDCardSizeUtil {
    public final String TAG = "SDCardSizeUtil";
    // class name
    private final static String CLASS_NAME = "android.os.storage.StorageVolume";
    // method name
    private final static String METHOD_GET_VOLUME_LIST = "getVolumeList";
    private final static String METHOD_GET_VOLUME_STATE = "getVolumeState";
    private final static String METHOD_IS_REMOVABLE = "isRemovable";
    private final static String METHOD_GET_PATH = "getPath";

    public static int defaultMinSizeMb = 80;

    private static SDCardSizeUtil INSTANCE = new SDCardSizeUtil();
    private static boolean isExternalPathExist = false;

    public static SDCardSizeUtil getInstance() {
        synchronized (SDCardSizeUtil.class) {
            return INSTANCE;
        }
    }

    public void init(final Context context) {
        TaskUtil.executeTask(new Runnable() {
            @Override
            public void run() {
                executeInit(context);
            }
        });
    }

    private void executeInit(Context context) {
        // external file path
        ConcurrentLinkedQueue<String> mExternalPathList = new ConcurrentLinkedQueue<String>();
        try {
            StorageManager mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
            if (mStorageManager != null) {
                Class<?> mStorageVolume = null;
                Method mGetVolumeListMethod = null;
                Method mGetVolumeStateMethod = null;
                Method mGetPathMethod = null;
                Method mIsRemovableMethod = null;
                Object[] mStorageVolumeList = null;

                mStorageVolume = Class.forName(CLASS_NAME);
                mGetVolumeListMethod = mStorageManager.getClass().getMethod(METHOD_GET_VOLUME_LIST, new Class[0]);
                mGetVolumeStateMethod = mStorageManager.getClass().getMethod(METHOD_GET_VOLUME_STATE, new Class[]{String.class});
                mIsRemovableMethod = mStorageVolume.getMethod(METHOD_IS_REMOVABLE, new Class[0]);
                mGetPathMethod = mStorageVolume.getMethod(METHOD_GET_PATH, new Class[0]);

                mStorageVolumeList = (Object[]) mGetVolumeListMethod.invoke(mStorageManager, new Object[0]);

                boolean mIsRemovable = false;

                if (mStorageVolumeList != null && mStorageVolumeList.length > 0) {
                    int mStorageVolumeCount = mStorageVolumeList.length;
                    Log.i(TAG, "init() === > StorageVolume Count = " + mStorageVolumeCount);

                    mExternalPathList.clear();

                    for (int i = 0; i < mStorageVolumeCount; ++i) {
                        String mStoragePath = (String) mGetPathMethod.invoke(mStorageVolumeList[i], new Object[0]);
                        mIsRemovable = ((Boolean) mIsRemovableMethod.invoke(mStorageVolumeList[i], new Object[0])).booleanValue();
                        if (!TextUtils.isEmpty(mStoragePath)) {
                            String state = (String) mGetVolumeStateMethod.invoke(mStorageManager, new Object[]{mStoragePath});
                            if ((state != null) && (state.equals(Environment.MEDIA_MOUNTED))) {
                                if (mIsRemovable) {
                                    Log.i(TAG, "init() === > external storage path = (" + mStoragePath + ")" + "||" + Environment.getExternalStorageDirectory().getPath());
                                    mExternalPathList.add(mStoragePath);
                                }
                            }
                        }
                    }
                }
                isExternalPathExist = isSdCardExist() && mStorageVolumeList.length > 1;
            } else {
                handleInvalid();
                Log.e(TAG, "init() === > can't get storage manager");
            }
        } catch (Exception e) {
            handleInvalid();
            Log.e(TAG, "init() === > Exception:" + e.getMessage());
        }

    }

    public static boolean isIsExternalPathExist() {
        return isExternalPathExist;
    }

    private void handleInvalid() {
        //do nothing now
    }

    /*存在，能正常读写，有足够空间*/
    public static void checkSDState(final Activity context) {
        if (checkSDExist(context) && canReadAndWrite(context) && checkEnoughSpace(context, defaultMinSizeMb)) {
            //is ok
        }
    }

    public static boolean checkSDExist(final Context context) {
        if (isSdCardExist()) {
            return true;
        }
        if (AQUtility.isUIThread()) {
            showNoSD(context);
        } else {
            AQUtility.post(new Runnable() {
                @Override
                public void run() {
                    showNoSD(context);
                }
            });
        }
        return false;
    }

    public static boolean canReadAndWrite(final Activity context) {
        boolean flag = true;
        Random rd = new Random();
        String testStr = "test" + rd.nextLong();
        File testFile = new File(Utility.getPhotoTempDir(), testStr);
        try {
            if (!(testFile.createNewFile() && testFile.delete())) {
                ToastMaker.showToastLong(context.getString(R.string.memory_exception));
                flag = false;
            }
        } catch (IOException e) {
            ToastMaker.showToastLong(context.getString(R.string.memory_exception));
            flag = false;
        } finally {
            testFile.deleteOnExit();
        }
        return flag;
    }

    public static boolean checkEnoughSpace(final Context context, int sizeMb) {
        if (isEnoughSpace(sizeMb)) {
            return true;
        }
        if (AQUtility.isUIThread()) {
            showNoEnoughSpace(context);
        } else {
            AQUtility.post(new Runnable() {
                @Override
                public void run() {
                    showNoEnoughSpace(context);
                }
            });
        }
        return false;
    }

    /*
     * SD是否存在
     * */
    public static boolean isSdCardExist() {
        return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
    }

    /*
     * 指定路径存储空间多少M
     * */
    public static long getAvailableMemorySize(String path) {
        if (null == path) return 0;
        long total = 0;
        try {
            StatFs stat = new StatFs(path);
            long blockSize = stat.getBlockSize();
            long availableBlocks = stat.getAvailableBlocks();
            total = availableBlocks * blockSize / (1024 * 1024);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return total;
    }

    /*
     * SD存储空间是否大于sizeMb M
     * */
    public static boolean isEnoughSpace(int sizeMb) {
        long availableSpare = 0;
        if (isSdCardExist()) {
            availableSpare = getAvailableMemorySize(Environment.getExternalStorageDirectory().getPath());
            APPLog.d("剩余空间", "availableSpare = " + availableSpare);
        }
        return availableSpare > sizeMb;
    }

    /*
    * 显示没有足够空间到对话框提示
    * */
    private static void showNoEnoughSpace(final Context context) {
        String errorMessage = context.getString(R.string.memory_forbid);
        String leftBtnText = context.getString(R.string.ok);
        if (isExternalPathExist) {
            errorMessage = context.getString(R.string.memory_forbid_1);
            leftBtnText = context.getString(R.string.more_detail);
        }
        if (context instanceof Activity && !((Activity) context).isFinishing()) {
            // TODO-kal
//            MMAlert.showAlert(context, errorMessage, "",
//                    context.getString(R.string.clear_cache),leftBtnText ,
//                    new DialogInterface.OnClickListener() {
//                        @Override
//                        public void onClick(DialogInterface dialogInterface, int i) {
//                            CommonFragmentActivity
//                                    .show(context, CacheInfoFragment.class.getName());
////                            ToastMaker.showToastLong(context.getString(R.string.cache_cleaning));
////                            TaskUtil.executeTask(new Runnable() {
////                                @Override
////                                public void run() {
////                                    KTVUtility.cleanOldCacheFiles();
////                                    ToastMaker.showToastLong(context.getString(R.string.cache_clean));
////                                }
////                            });
//                        }
//                    }, new DialogInterface.OnClickListener() {
//                        @Override
//                        public void onClick(DialogInterface dialogInterface, int i) {
//                            if(isExternalPathExist){
//                                SmallBrowserFragment.showActivity(context, ChangbaConstants.SDCARD_HELP_INFO);
//                            }
//                            dialogInterface.dismiss();
//                        }
//                    });
        } else {
            ToastMaker.showToastLong(errorMessage);
        }


    }

    /*
     * 显示没有SD卡到提示
     * */
    private static void showNoSD(Context context) {
        String errorMessage = context.getString(R.string.no_sdcard);
        if (context instanceof Activity && !((Activity) context).isFinishing()) {
            // TODO-kal
//            MMAlert.showAlert(context,errorMessage,"",new DialogInterface.OnClickListener() {
//                @Override
//                public void onClick(DialogInterface dialogInterface, int i) {
//                    dialogInterface.dismiss();
//                }
//            });
        } else {
            ToastMaker.showToastLong(errorMessage);
        }
    }
}